package showtime.framework.engine.map.rpg
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import showtime.framework.component.pool.ObjectPool;
	import showtime.framework.engine.IEntity;
	
	public class MapLayer extends Sprite implements IEntity
	{
		public var data:Vector.<int> = null;
		public var type:String = null;	
		
		public var layerWidth:int = 0;
		public var layerHeight:int = 0;
		
		private var map:RPGGameMap = null;
		
		public var tileWidth:int = 0;
		public var tileHeight:int = 0;
		
		private var _imageTileWidth:int = 0;
		private var _imageTileHeight:int = 0;
		
		private var tileMap:Object = null;
		
		private var scrollX:int = 0;
		private var scrollY:int = 0;
		
		private var maxScrollX:int = 0;
		private var maxScrollY:int = 0;
		
		private var tileCache:Object = null;
		private var pool:ObjectPool = null;
		
		public function MapLayer(type:String, width:int, height:int, tileWidth:int , tileHeight:int, imageTileWidth:int, imageTileHeight:int)
		{
			this.type = type;
			data = new Vector.<int>();
			tileMap = {};
			tileCache = {};
			
			layerWidth = width;
			layerHeight = height;
			
			this.tileWidth = tileWidth;
			this.tileHeight = tileHeight;
			
			_imageTileHeight = imageTileHeight;
			_imageTileWidth = imageTileWidth;			
			
		}
		
		public function destroy():void
		{
			map = null;			
			data = null;
			
			for (var key:String in tileCache)
			{
				tileCache[key].dispose();
				delete tileCache[key];
			}
		}
		
		public function update():void
		{		
			if (map == null)
			{
				return;
			}
			
			scrollX = map.target.x - (map.visibleWidth >> 1);
			scrollY = map.target.y - (map.visibleHeight >> 1);
			
			maxScrollX = (layerWidth * tileWidth) - map.visibleWidth;
			maxScrollY = (layerHeight * tileHeight) - map.visibleHeight;
			
			scrollX = scrollX < 0 ? 0 : scrollX > maxScrollX ? maxScrollX : scrollX;
			scrollY = scrollY < 0 ? 0 : scrollY > maxScrollY ? maxScrollY : scrollY;
			
			map.objectLayer.x = -scrollX;
			map.objectLayer.y = -scrollY;
			
			x = -scrollX;
			y = -scrollY;
			
		}
		
		public function render():void
		{
			if (map != null)
			{
				if (!checkMap())
				{
					return;
				}
				
				map.camera.x = int(map.target.x / tileWidth);
				map.camera.y = int(map.target.y / tileHeight);
				
				var startX:int = (map.camera.x - map.preloadX < 0 ? 0 : map.camera.x - map.preloadX);
				var startY:int = (map.camera.y - map.preloadY < 0 ? 0 : map.camera.y - map.preloadY);
				
				var endX:int = (map.camera.x + map.preloadX > layerWidth ? layerWidth : map.camera.x + map.preloadX);
				var endY:int = (map.camera.y + map.preloadY > layerHeight ? layerHeight : map.camera.y + map.preloadY);
				
				unload(startX, endX, startY, endY);
				
				var index:int = 0;		
				for (var row:int = startY; row < endY; row++)
				{
					for (var col:int = startX; col < endX; col++)
					{
						if (tileMap.hasOwnProperty(col + "_" + row))
						{
							continue;
						}
						
						index = data[layerWidth * row + col] - 1;
						
						if (!tileCache.hasOwnProperty(index))
						{
							tileCache[index] = new BitmapData(tileWidth, tileHeight);
							tileCache[index].copyPixels(map.buffer, new Rectangle((index - int(index /_imageTileWidth) * _imageTileWidth) * tileWidth, int(index /_imageTileWidth) * tileHeight, tileWidth, tileHeight), new Point());
						}

						var tile:Bitmap = Bitmap(pool.getObject());
						tile.smoothing = true;
						
						if (tile.bitmapData != tileCache[index])
						{
							tile.bitmapData = tileCache[index];
						}
				
						tile.visible = true;
						tile.x = col * tileWidth;
						tile.y = row * tileHeight;
						
						tileMap[col + "_" + row] = tile;
						
						if (tile.parent == null)
						{
							addChild(tile);
						}
						
					}
				}			
				
			}
			
		}
		
		
		public function register(map:*):void
		{
			this.map = map;
			
			pool = new ObjectPool(Bitmap, int(map.visibleWidth / tileWidth * map.visibleHeight / tileHeight));
			map.addChild(this);
		}
		
		private function checkMap():Boolean
		{
			var nowScreenX:int = int(map.target.x / tileWidth);
			var nowScreenY:int = int(map.target.y / tileHeight);
			
			if (nowScreenX != map.camera.x || nowScreenY != map.camera.y)
			{
				return true;
			}
			
			return false;
			
		}
		
		private function unload(startX:int , endX:int, startY:int , endY:int):void
		{
			for (var key:String in tileMap)
			{
				var temp:Array = key.split("_");
				if (temp[0] + 1 < startX || temp[0] + 1 > endX || temp[1] + 1 < startY || temp[1] + 1 > endY)
				{
					pool.dispose(tileMap[key]);
					
					delete tileMap[key];
					
				
				}
			}
		}
		
		
	}
}